package chap_02_CAS.step_02_Atomic;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * @Description 对象的属性修改原子类
 * @Author shihan
 * @Date 2022/10/30 11:37
 * @Version 1.0
 */
public class Atomic_03_ReferenceFieldUpdater {

    public volatile Boolean isInit = Boolean.FALSE;

    private AtomicReferenceFieldUpdater<Atomic_03_ReferenceFieldUpdater, Boolean> fieldUpdater =
            AtomicReferenceFieldUpdater.newUpdater(
                    Atomic_03_ReferenceFieldUpdater.class,
                    Boolean.class,
                    "isInit"
            );

    public void init() {
        // currentValue 和 expectValue 的判断，依然是 == 地址是否相等的判断
        if (fieldUpdater.compareAndSet(this, Boolean.FALSE, Boolean.TRUE)) {
            System.out.println(Thread.currentThread().getName() + "\t" + "正在初始化...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "\t" + "初始化结束...");
        } else {
            System.out.println(Thread.currentThread().getName() + "\t" + "其他线程已经在进行初始化...");
        }
    }

    public static void main(String[] args) {
        Atomic_03_ReferenceFieldUpdater updater = new Atomic_03_ReferenceFieldUpdater();
        CountDownLatch countDownLatch = new CountDownLatch(5);

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    updater.init();
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("主线程关闭！");
        // 为什么 == 返回是 true，因为他们是 static 静态的，和 Boolean 类绑定，所以地址指向是一样的
        System.out.println(Boolean.FALSE == Boolean.FALSE);
    }

}
